/**
 * 多 Tab 分布式 token 刷新器
 * 对外唯一入口：refreshAccessToken()
 */
import store from '@/store';
import {getAccessTokenByRefreshToken} from '@/api/mgt/power/auth';
import {resetLogin} from '@/utils/index';

/* ========== 常量 ========== */
const LOCK_KEY = 'token_refresh_lock';
const LOCK_TTL = 15 * 1000;
const REFRESHING_KEY = 'token_refreshing';
const LOCK_DELAY_KEY = 'token_refresh_delay';
const LOCK_DELAY_TTL = 100;
const sessionId = `${Date.now()}-${Math.random()}`;

/* ========== 内存变量（单 Tab）========== */
let memoryRefreshing = false;
let promiseMap = null;

/* -------------------------------------------------- */
export const refreshAccessToken = async () => {
    /* 0. 刷新页面后 100ms 内禁止竞争锁 */
    const delayLock = localStorage.getItem(LOCK_DELAY_KEY);
    if (delayLock && Date.now() - parseInt(delayLock, 10) < LOCK_DELAY_TTL) {
        await sleep(LOCK_DELAY_TTL);
        return refreshAccessToken();
    }

    /* 1. 本 Tab 内存幂等 */
    if (memoryRefreshing) {
        await waitForStorageUnrefreshed();
        return {accessToken: store.state.userToken.access_token, isRefresher: false};
    }

    /* 2. 分布式锁：决定谁去真正刷新 */
    const lock = await acquireLock();
    if (!lock.isRefresher) {
        await waitForStorageUnrefreshed(); // 👈 等待并返回令牌
        return {accessToken: store.state.userToken.access_token, isRefresher: false};
    }

    /* 3. 本 Tab 成为刷新者 */
    if (!promiseMap) {
        console.log('[refreshAccessToken] 本 Tab 成为刷新者');
        localStorage.setItem(LOCK_DELAY_KEY, String(Date.now()));
        memoryRefreshing = true;
        localStorage.setItem(REFRESHING_KEY, '1');
        promiseMap = (async () => {
            const rt = store.state.userToken?.refresh_token;
            if (!rt) {
                resetLogin();
                throw new Error('no refresh_token');
            }
            store.commit('setIsRefreshing', true);
            let atk;
            try {
                const res = await getAccessTokenByRefreshToken(rt);
                atk = res?.bizData?.access_token;
                if (!atk) throw new Error('empty access_token');
                store.commit('setUserToken', {...store.state.userToken, ...res.bizData});
                console.log('[refreshAccessToken] 刷新成功', atk);
            } catch (e) {
                store.commit('clearRetryQueue');
                resetLogin();
                throw e;
            } finally {
                store.commit('setIsRefreshing', false);
            }
            /* 重放队列 */
            const queue = [...store.state.retryQueue];
            store.commit('clearRetryQueue');
            queue.forEach(cb => cb());
            return atk;
        })().finally(() => {
            promiseMap = null;
            memoryRefreshing = false;
            localStorage.removeItem(REFRESHING_KEY);
            localStorage.removeItem(LOCK_DELAY_KEY);
            releaseLock();
        });
    }

    const atk = await promiseMap;
    return {accessToken: atk, isRefresher: true};
};

/* -------------------------------------------------- */
const acquireLock = async () => {
    const now = Date.now();
    const lock = JSON.parse(localStorage.getItem(LOCK_KEY) || 'null');
    if (!lock || now - lock.timestamp > LOCK_TTL) {
        localStorage.setItem(LOCK_KEY, JSON.stringify({sessionId, timestamp: now}));
        await sleep(100);
        const cur = JSON.parse(localStorage.getItem(LOCK_KEY));
        return cur?.sessionId === sessionId ? {isRefresher: true} : {isRefresher: false};
    }
    return {isRefresher: false};
};

const releaseLock = () => {
    const lock = JSON.parse(localStorage.getItem(LOCK_KEY) || 'null');
    if (lock?.sessionId === sessionId) localStorage.removeItem(LOCK_KEY);
};

const sleep = ms => new Promise(r => setTimeout(r, ms));

const waitForStorageUnrefreshed = () =>
    new Promise(resolve => {
        if (!localStorage.getItem(REFRESHING_KEY)) return resolve();
        const timer = setInterval(() => {
            if (!localStorage.getItem(REFRESHING_KEY)) {
                clearInterval(timer);
                resolve();
            }
        }, 50);
    }).then(() => {
        // 👇 不重新调用 refreshAccessToken，而是直接返回最新令牌
        return {accessToken: store.state.userToken.access_token, isRefresher: false};
    });

/* 可选：监听其它 Tab 刷新完成 */
window.addEventListener('storage', e => {
    if (e.key === REFRESHING_KEY && !e.newValue) {
        const queue = [...store.state.retryQueue];
        if (queue.length) {
            store.commit('clearRetryQueue');
            queue.forEach(cb => cb());
        }
    }
});
